package com.zretc.auth.service;

import com.zretc.api.pojo.MessageEvent;
import com.zretc.api.pojo.RegisterDTO;
import com.zretc.api.pojo.SysUser;
import com.zretc.api.pojo.UpdatePasswordDTO;
import com.zretc.auth.dao.SysUserMapper;
import com.zretc.common.constant.SecurityConstant;
import com.zretc.common.constant.WebConstant;
import com.zretc.common.entity.R;
import com.zretc.common.entity.RespResult;
import com.zretc.common.util.JwtUtil;
import com.zretc.redis.service.RedisService;
import com.zretc.security.entity.LoginUser;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class LoginService {
    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    RedisService redisService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    public RespResult login( SysUser user){
        SysUser srcUser = sysUserMapper.getUserByName(user.getUser_name());
        //验证用户名
        if(Objects.isNull(srcUser)){
           return R.fail(WebConstant.LOGIN_ERROR_CODE,WebConstant.ERROR_408);
        }
        //验证密码
        if(!new BCryptPasswordEncoder().matches(user.getPassword(),srcUser.getPassword())){
            return R.fail(WebConstant.LOGIN_ERROR_CODE,WebConstant.ERROR_408);
        }
        //如果登录成功- 直接查询权限列表
        ArrayList<String> roleList = sysUserMapper.getRoleList(srcUser.getId());
        //封装权限模型
        LoginUser loginUser = new LoginUser(srcUser, roleList, null);
        //根据userId生成JWT字符串
        String token = JwtUtil.createJWT(String.valueOf(srcUser.getId()));
        //存储登录信息到redis
        redisService.setCacheObject("login:" + srcUser.getId(),loginUser);
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put(SecurityConstant.AUTHENTICATION_HEADER_NAME,token);
        resultMap.put("purview",roleList);
        //如果有必要 同时相应用户名和头像等操作  srcUser
        // 检查是否是当天首次登录并增加积分
        String loginKey = "user:login:" + srcUser.getId() + ":" + LocalDate.now();
        if (Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(loginKey, "1", 1, TimeUnit.DAYS))) {
            MessageEvent messageEvent = new MessageEvent();
            messageEvent.setUserId(srcUser.getId());
            messageEvent.setAction("login");
            messageEvent.setTimestamp(System.currentTimeMillis());
            rocketMQTemplate.convertAndSend("addPointsTopic",messageEvent);
            // 假设每次登录增加10个积分
            System.out.println("用户 " + srcUser.getId() + " 今天首次登录，积分已增加");
        } else {
            System.out.println("用户 " + srcUser.getId() + " 今天已经登录过，积分未增加");
        }

        return R.success(resultMap);


    }

    public RespResult logout() {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String key =  "login:" +loginUser.getUser().getId();
        redisService.deleteCacheWithPrefix(key);
        return R.success("成功登出");
    }

    @Transactional
    public RespResult updatePassword(UpdatePasswordDTO updatePasswordDTO) {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        int userId = loginUser.getUser().getId();
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        if(bCryptPasswordEncoder.matches(updatePasswordDTO.getOldpassword(),loginUser.getUser().getPassword())){
            if(updatePasswordDTO.getNewpassword().equals(updatePasswordDTO.getRepnewassword())){
                String newpass = bCryptPasswordEncoder.encode(updatePasswordDTO.getNewpassword());
                if(sysUserMapper.updatePassword(newpass,userId)){
                    //踢回登陆界面
                    redisService.deleteObject("login:" + loginUser.getUser().getId());
                    return R.success("密码修改成功");
                }
                else {
                    return R.fail(550,"新密码两次输入不一致");
                }
            }

        }
        return R.fail(512,"旧密码输入不正确，请重新输入");

    }

    @Transactional
    public RespResult register(RegisterDTO registerDTO) {
        if(registerDTO.getUser_name() == null || registerDTO.getUser_name().equals("")){
            return R.fail(WebConstant.LOGIN_ERROR_CODE,"请填写用户名");
        }
        if(sysUserMapper.getUserByName(registerDTO.getUser_name()) != null){
            return R.fail(WebConstant.LOGIN_ERROR_CODE,"用户名已存在，请重新输入");
        }
        else if(registerDTO.getPassword() == null || registerDTO.getPassword().equals("")){
            return R.fail(WebConstant.LOGIN_ERROR_CODE,"请填写密码");
        }
        else if(!registerDTO.getPassword().equals(registerDTO.getPrepassword())){
            return R.fail(WebConstant.LOGIN_ERROR_CODE,"密码两次输入不相同，请重试");
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(registerDTO,sysUser);
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        sysUser.setPassword(bCryptPasswordEncoder.encode(registerDTO.getPassword()));
        if(sysUserMapper.register(sysUser)){
            int Id = sysUserMapper.getIdByUsername(sysUser.getUser_name());
            sysUserMapper.initRole(Id);
            return R.success("注册成功");
        }
        return R.fail(600,"注册失败");

    }
}
